#include "defaults.h"
#include "nurbs.h"
#include "primitivemanager.h"

PrimitiveManager* PrimitiveManager::instance = 0;

PrimitiveManager::PrimitiveManager() {

}

void PrimitiveManager::AddPrimitive(Primitive* p, const std::string& label) {
	InitializeRenderer(p);
}

void PrimitiveManager::RemovePrimitive(Primitive* p) {}

void PrimitiveManager::Clear() {
	for(size_t i = 0; i < primitive.size(); i++)
		delete primitive[i];
	primitive.resize(0);
}

PrimitiveRenderer* PrimitiveManager::GetCurrentPrimitiveRenderer() {
	PrimitiveRenderer* pr = primitive.back();
	return pr;
}

Primitive* PrimitiveManager::GetCurrentPrimitive() {
	PrimitiveRenderer* pr = GetCurrentPrimitiveRenderer();
	if(pr)
		return pr->GetPrimitive();
	return 0;
}

PrimitiveRenderer* PrimitiveManager::GetPrimitiveRenderer(size_t i) {
	if(i >= primitive.size()) {
		std::cerr << "error: there are only " << primitive.size() << " primitives." << std::endl;
		return 0;
	}
		
	return primitive[i];
}

Primitive* PrimitiveManager::GetPrimitive(size_t i) {
	PrimitiveRenderer* pr = GetPrimitiveRenderer(i);
	if(!pr)
		return 0;
	return pr->GetPrimitive();
}

size_t PrimitiveManager::Size() const {return primitive.size();}

void PrimitiveManager::Update() {
	for(size_t i = 0; i < primitive.size(); i++) {
		primitive[i]->Update();
	}
}

void PrimitiveManager::Render() const {
	for(size_t i = 0; i < primitive.size(); i++)
		primitive[i]->Render();
}

PrimitiveManager* PrimitiveManager::Instance() {
	if(!instance) {
		instance = new PrimitiveManager();
	}
	return instance;
}

void PrimitiveManager::InitializeRenderer(Primitive* primitive) {
	primitive->Dispatch(this);
}

void PrimitiveManager::Visit(Surface* surface) {
	Vec3n color = PrimitiveRenderer::Color(1);
	SurfaceRenderer* sr = new SurfaceRenderer(surface, 8, math::V2n(0.0, 1.0), math::V2n(0.0, 1.0), color, true, true);
	primitive.push_back(sr);
}

void PrimitiveManager::Visit(STriangleMesh* tm) {
	Vec3n color = PrimitiveRenderer::Color(1);
	TriangleMeshRenderer* tmr = new TriangleMeshRenderer(tm, color);
	primitive.push_back(tmr);
}

void PrimitiveManager::Visit(NurbsSurfaceMesh* mesh) {
	primitive.push_back(new NurbsSurfaceRenderer(mesh));
}

void PrimitiveManager::Visit(Curve* curve) {
	Vec3n color = PrimitiveRenderer::Color(3);
	CurveRenderer* cr = new CurveRenderer(curve, 8, color, true, true);
	primitive.push_back(cr);
}
